import LoginResponse from '@/structure/loginResponse';
import TokenInfo from '@/structure/tokenInfo';
import User from '@/structure/user';
import Cookies from 'js-cookie';

const PREFIX = process.env.VUE_APP_COOKIE_PREFIX;
const DOMAIN = process.env.VUE_APP_DOMAIN;

function setItem(key: string, value: any): void {
  if (value === null || value === undefined) {
    return;
  }
  Cookies.set(PREFIX + key, JSON.stringify(value), {
    domain: DOMAIN
  });
}

function getItem(key: string): string | null {
  return Cookies.get(PREFIX + key);
}

function removeItem(key: string): void {
  Cookies.remove(PREFIX + key, {
    domain: DOMAIN
  });
}

/**
 * 用户工具类
 */
class UserUtils {

  /**
   * 保存登录信息
   * @param data 登录响应
   */
  public static set(data: LoginResponse<User>): void {
    setItem('user', data.info);
    setItem('permissionKeys', data.permissionKeys);
    setItem('accessToken', data.accessToken);
    setItem('refreshToken', data.refreshToken);
  }

  /**
   * 保存用户
   * @param data 用户信息
   */
  public static setUser(data: User): void {
    setItem('user', data);
  }

  /**
   * 清理缓存
   */
  public static clean(): void {
    removeItem('user');
    removeItem('permissionKeys');
    removeItem('accessToken');
    removeItem('refreshToken');
  }

  /**
   * 获取数据令牌
   * @return 数据令牌
   */
  public static getAccessToken(): string | null {
    return UserUtils.getToken('accessToken');
  }

  /**
   * 获取刷新令牌
   * @return 刷新令牌
   */
  public static getRefreshToken(): string | null {
    return UserUtils.getToken('refreshToken');
  }

  /**
   * 获取当前用户信息
   * @return 当前用户信息
   */
  public static getUser(): User {
    const obj = UserUtils.parseObj('user');
    return (UserUtils.isObj(obj) ? obj : {}) as User;
  }

  /**
   * 判断当前用户是否拥有指定权限
   * @return 是否拥有指定权限
   */
  public static hasPermission(keys: string[]): boolean {
    const keyList = Array.isArray(keys) ? keys : [keys];
    let data = getItem('permissionKeys');
    data = data !== undefined ? '[]' : data;
    const obj = JSON.parse(data);
    const permissionKeys = Array.isArray(obj) ? obj : [];

    return keyList.some((key) => permissionKeys.includes(key));
  }

  private static getToken(key: string): string | null {
    const obj = UserUtils.parseObj(key);
    const tokenInfo = (UserUtils.isObj(obj) ? obj : {}) as TokenInfo;
    const token = tokenInfo.token;
    const expireAt = tokenInfo.expireAt;

    if (token === undefined) {
      return null;
    } else if (expireAt === undefined) {
      return token;
    } else {
      const now = Date.now();
      return now > expireAt ? null : token;
    }
  }

  private static parseObj(key: string): object {
    let data = getItem(key);
    data = (data === undefined || data === null) ? '{}' : data;
    return JSON.parse(data);
  }

  private static isObj(obj: any): boolean {
    return typeof obj === 'object' && !Array.isArray(obj);
  }
}

export default UserUtils;
